1 /*
2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021
3 License:   [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License].
4 Authors: Marcelo S. N. Mancini
5 
6 	Copyright Marcelo S. N. Mancini 2018 - 2021.
7 Distributed under the CC BY-4.0 License.
8    (See accompanying file LICENSE.txt or copy at
9 	https://creativecommons.org/licenses/by/4.0/
10 */
11 module hip.util.time;
12 import core.stdc.time;
13 
14 version(Windows)
15 {
16     import core.sys.windows.windef;
17     extern(Windows) BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpPerformanceCount) nothrow;
18     extern(Windows) BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount) nothrow;
19 }
20 else version(WebAssembly)
21 {
22     extern(C) size_t monotimeNow() @nogc nothrow;
23 }
24 else
25 {
26     import core.stdc.config:c_long;
27     enum CLOCK_MONOTONIC = 1;
28     struct timespec
29     {
30         int tv_sec; //Seconds
31         c_long tv_nsec; //Nanoseconds
32     }
33     extern(C) int clock_gettime(int clock_id, timespec* tm) nothrow;
34 }
35 
36 ulong getSystemTime() nothrow
37 {
38     version(Windows)
39     {
40         LARGE_INTEGER counter = void;
41         QueryPerformanceCounter(&counter);
42         return counter.QuadPart * 1_000_000_000; //Convert to nanos
43     }
44     else version(WebAssembly)
45     {
46         return monotimeNow();
47     }
48     else
49     {
50         timespec tm = void;
51         if(clock_gettime(CLOCK_MONOTONIC, &tm))
52             return 0;
53         return cast(size_t)(tm.tv_nsec + tm.tv_sec * 1e9);
54     }
55 }
56 private ulong getSystemTicksPerSecond() nothrow
57 {
58     version(Windows)
59     {
60         LARGE_INTEGER ticksPerSecond = void;
61         QueryPerformanceFrequency(&ticksPerSecond);
62         return ticksPerSecond.QuadPart;
63     }
64     else
65     {
66         return 0;
67     }
68 }
69 
70 class HipTime
71 {
72 
73     private __gshared ulong startTime;
74     private __gshared ulong ticksPerSecond;
75     protected __gshared long[string] performanceMeasurement;
76 
77     static void initialize()
78     {
79         ticksPerSecond = getSystemTicksPerSecond();
80         startTime =  getSystemTime();
81     }
82 
83     static long getCurrentTime() nothrow
84     {
85         ulong time = 0;
86         version(Windows)
87         {
88             time = (getSystemTime() - startTime) / ticksPerSecond;
89         }
90         else
91             time = getSystemTime() - startTime;
92         return time;
93     }
94 
95     static float getCurrentTimeAsMilliseconds() nothrow
96     {
97          version(WebAssembly)
98             return cast(float)getCurrentTime();
99         else
100             return cast(float)getCurrentTime() / 1_000_000;
101     }
102     static float getCurrentTimeAsSeconds() nothrow
103     {
104          version(WebAssembly)
105             return getCurrentTime() / 1_000;
106         else
107             return cast(float)getCurrentTime() / 1_000_000_000;
108     }
109 
110     static void initPerformanceMeasurement(string name)
111     {
112         performanceMeasurement[name] = getCurrentTime();
113     }
114     static void finishPerformanceMeasurement(string name)
115     {
116         // import std.stdio:writeln;
117         // writeln(name, " took ", (getCurrentTime() - performanceMeasurement[name])/1_000_000, "ms");
118     }
119 
120     static struct Profiler
121     {
122         private string name;
123         this(string name){this.name = name;HipTime.initPerformanceMeasurement(name);}
124         ~this(){HipTime.finishPerformanceMeasurement(name);}
125     }
126     static mixin template Profile(string name){mixin("HipTime.Profiler _profile"~name~" = HipTime.Profiler("~name~");");}
127     static mixin template ProfileFunction(){mixin("HipTime.Profiler _profileFunc = HipTime.Profiler(__PRETTY_FUNCTION__);");}
128 }
129 
130 float seconds(float v){return v;}
131 float msecs(float v){return v*1_000;}
132 float usecs(float v){return v*1_000_000;}
133 float nsecs(float v){return v*1_000_000_000;}